package org.jackysoft.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.Barcode;
import com.itextpdf.text.pdf.Barcode128;
import com.itextpdf.text.pdf.BarcodeEAN;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.GrayColor;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPRow;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFConveter {
	static final Log logger = LogFactory.getLog(PDFConveter.class);

	public PDFConveter() {
		super();
		// TODO Auto-generated constructor stub
	}

	public PDFConveter(String path, String pdfname, String fontsHome,
			String titlePost, String keywords, String title, ReportType xlsType) {
		this();
	}

	public PDFConveter(byte[] data, String pdfname, String fontsHome,
			String titlePost, String keywords, String title, ReportType xlsType) {
	}

	/**
	 * @param path
	 *            xls 源文件路径
	 * @param pdfname
	 *            pdf 目标文件路径
	 * @param fontsHome
	 *            字体路径
	 * @param titlePost
	 *            标题后缀
	 * @param keywords
	 *            关键字
	 * @param title
	 *            主题
	 * @param fullDate
	 *            表格有效列数
	 * 
	 * @throws java.io.IOException
	 * @throws DocumentException
	 * @throws BiffException
	 **/
	public void convert(String path, String pdfname, String fontsHome,
			String titlePost, String keywords, String title, ReportType xlsType,DateTime date)
			throws IOException, DocumentException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		IOUtils.copy(new FileInputStream(new File(path)),
				output);
		this.convert(output.toByteArray(), pdfname, fontsHome, titlePost,
				keywords, title, xlsType,date);
	}

	/**
	 * @param data
	 *            excel数据流
	 * */

	public void convert(byte[] data, String pdfname, String fontsHome,
			String titlePost, String keywords, String title, ReportType xlsType,DateTime date)
			throws IOException, DocumentException {
		// 左、右、上、下页边距
		Document pdfdoc = new Document(PageSize.A4.rotate(), 20, 20, 20, 20);

		PdfWriter pdfwriter = PdfWriter.getInstance(pdfdoc,
				new FileOutputStream(pdfname));

		//pdfwriter.setViewerPreferences(~PdfWriter.HideWindowUI & ~PdfWriter.HideToolbar);
		preProcess(pdfdoc, pdfwriter, titlePost, keywords, fontsHome, title,date);
		parseExcel(data, fontsHome, xlsType, pdfdoc);
		pdfEncryptor(pdfdoc, pdfwriter);
		pdfdoc.close();
	}

	void justifyTableHeader(ReportType type, PdfPTable table, String sheetName)
			throws DocumentException, IOException {
		if (type == null)
			return;
		switch (type) {
		case 生产日报:			
			break;
		case 重点品种:			
			break;
		case 生产月报:
			renderMonth(table, sheetName);
			break;
		default:
			break;
		}

	}

	private void renderMonth(PdfPTable table, String sheetName)
			throws DocumentException, IOException {

		int hrow = 0;
		PdfPCell[] cells = table.getRow(hrow).getCells();
		PdfPCell pcell = cells[0];
		pcell.setColspan(cells.length);

		String idx = sheetName.substring(sheetName.indexOf('-') + 1);
		BaseFont bfTitle = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",
				BaseFont.EMBEDDED);
		Font titleFont = new Font(bfTitle, 20, Font.BOLD);		

		String cnt = pcell.getPhrase().getContent();

		PdfPRow phrow = table.getRow(2);
		PdfPCell[] phcells = phrow.getCells();
		int i = Integer.parseInt(idx);
		logger.info(i + " 报表类型 ");
		int[] cidx = null;
		switch (i) {
		case 1:
			// cnt="生 产月报表";
			cidx = new int[] { 2, 4, 6, 8, 10 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.setColspan(2);
				c.setHorizontalAlignment(Element.ALIGN_CENTER);
			}
			break;
		case 2:
			// cnt="自制半成品、成品收发月报 ";
			cidx = new int[] { 2, 4, 6, 8, 10 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.setColspan(2);
				c.setHorizontalAlignment(Element.ALIGN_CENTER);
			}
			break;
		case 3:
			// cnt="自制半成品、成品收发月报";
			cidx = new int[] { 3, 5, 7, 9, 11 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.setColspan(2);
				c.setHorizontalAlignment(Element.ALIGN_CENTER);
			}
			cidx = new int[] { 0, 1, 2 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.disableBorderSide(Rectangle.BOTTOM);
				c.setRowspan(2);
				c.setVerticalAlignment(Element.ALIGN_CENTER);
			}
			PdfPRow tr = table.getRow(3);
			PdfPCell[] trc = tr.getCells();
			for (int ci : cidx) {
				PdfPCell c = trc[ci];
				c.setRowspan(2);
				c.setVerticalAlignment(Element.ALIGN_CENTER);
			}
			break;
		case 4:
			// cnt="外协半成品收发结存月报";
			cidx = new int[] { 2, 4, 6, 8 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.setColspan(3);
				c.setHorizontalAlignment(Element.ALIGN_CENTER);
			}

			break;
		case 5:
			// cnt="产品试验月报表";
			cidx = new int[] { 2, 4, 6, 8 };
			for (int ci : cidx) {
				PdfPCell c = phcells[ci];
				c.setColspan(2);
				c.setHorizontalAlignment(Element.ALIGN_CENTER);
			}

			break;
		default:
			break;

		}

		Paragraph titleP = new Paragraph(cnt, titleFont);
		titleP.setAlignment(Element.ALIGN_CENTER);
		titleP.setFont(titleFont);
		pcell.addElement(titleP);
		// table.deleteRow(0);

	}

	void preProcess(Document pdfdoc, PdfWriter pdfwriter, String titlePost,
			String keywords, String fontsHome, String title,DateTime date)
			throws DocumentException, IOException {
		pdfwriter
				.setEncryption(new byte[0], new byte[0],
						PdfWriter.ALLOW_DEGRADED_PRINTING,
						PdfWriter.ENCRYPTION_AES_128);

		pdfwriter.setViewerPreferences(PdfWriter.HideMenubar
				| PdfWriter.HideToolbar);

		pdfwriter.setViewerPreferences(PdfWriter.HideWindowUI);
		// 标题、主题、作者、关键字、装订方式、创建者、生产者、创建日期
	
		if(date==null)date=DateTime.now();			
		pdfdoc.addTitle(date.toString("Y-M-d"+title));
		pdfdoc.addSubject(titlePost);
		pdfdoc.addKeywords(keywords);
		pdfdoc.addAuthor("屈甲康");
		pdfdoc.addCreator("qujiakang@126.com");
		pdfdoc.addProducer();
		pdfdoc.addCreationDate();
		pdfdoc.addHeader("header", "内容");
		// 其中方法addHeader对于PDF文档无效，addHeader仅对html文档有效，用于添加文档的头信息

		pdfwriter.setPageEvent(new Watermark());
		pdfdoc.open();

		// 标题字体
		BaseFont bfTitle = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",
				BaseFont.EMBEDDED);
		Font titleFont = new Font(bfTitle, 20, Font.BOLD);
		// BaseFont bfComic = BaseFont.createFont("STSong-Light",
		// "UniGB-UCS2-H", BaseFont.EMBEDDED);

		Paragraph titleP = new Paragraph(title, titleFont);
		titleP.setAlignment(Element.ALIGN_CENTER);
		pdfdoc.add(titleP);
	}

	void pdfEncryptor(Document pdfdoc, PdfWriter pdfwriter)
			throws DocumentException {
		PdfContentByte cb = pdfwriter.getDirectContent();
		BarcodeEAN codeEAN = new BarcodeEAN();
		codeEAN.setCodeType(Barcode.EAN13);
		String time = System.currentTimeMillis() + "";
		codeEAN.setCode(time);
		codeEAN.setAltText(time);
		Image imageEAN = codeEAN.createImageWithBarcode(cb, BaseColor.BLACK,
				BaseColor.BLUE);
		pdfdoc.add(new Phrase(new Chunk(imageEAN, 500, -20)));

		Barcode128 code = new Barcode128();
		char[] chars = "屈甲康".toCharArray();
		String icode = "";
		for (Character c : chars) {
			icode += (c + 1);
		}
		code.setCode(icode);
		Image code128 = code.createImageWithBarcode(cb, BaseColor.BLACK,
				BaseColor.BLUE);
		pdfdoc.add(new Phrase(new Chunk(code128, 510, -20)));
	}

	public void parseExcel(byte[] data, String fontsHome, ReportType xlsType,
			Document pdfdoc) throws DocumentException, IOException {

		BaseFont bfComic = BaseFont.createFont(fontsHome, BaseFont.IDENTITY_H,
				BaseFont.NOT_EMBEDDED);
		Font font = new Font(bfComic, 12, Font.NORMAL);
		Workbook workbook = new HSSFWorkbook(new ByteArrayInputStream(data));
		int snum = workbook.getNumberOfSheets();
		for (int i = 0; i < snum; i++) {
			Sheet sheet = workbook.getSheetAt(i);

			Iterator<Row> rows = sheet.rowIterator();

			Row firstRow = rows.hasNext() ? rows.next() : null;

			int columns = 7;

			if (firstRow != null && firstRow.getPhysicalNumberOfCells() != 0) {

				columns = firstRow.getPhysicalNumberOfCells();

			} else {
				logger.error(sheet.getSheetName() + " 没有设置标志行");
				break;
				// throw new java.lang.IllegalStateException("没有设置标志行0");
			}

			float[] widths = new float[columns];
			int f = 0;
			for (Iterator<Cell> citr = firstRow.cellIterator(); citr.hasNext()
					&& f < columns;) {
				Cell cl = citr.next();
				widths[f++] = ExcelUtil.cellNumber(cl).floatValue();
			}
			logger.info("检测到有效范围为   [ " + sheet.getPhysicalNumberOfRows()
					+ " 行," + columns + " 列]");
			PdfPTable table = new PdfPTable(columns);
			table.setWidthPercentage(100f);
			table.setSpacingBefore(20f);// 防止与上面文字重叠
			table.setWidths(widths);
			for (; rows.hasNext();) {
				Row row = rows.next();
				int numofcell = row.getPhysicalNumberOfCells();

				if (numofcell == 0)
					continue;
				if (columns > numofcell)
					columns = numofcell;

				byte[] eps = new byte[columns];
				logger.info(sheet.getSheetName() + " , 第 " + row.getRowNum()
						+ " 行,共 " + row.getPhysicalNumberOfCells() + " 列 , 最大 "
						+ columns + "列");
				byte[] fulleps = new byte[columns];
				Paragraph[] pdfparag = new Paragraph[columns];

				for (int c = 0; c < columns; c++) {
					Cell cell = row.getCell(c);
					fulleps[c] = 0;
					String cnt = ExcelUtil.cellString(cell, c != 0);
					pdfparag[c] = new Paragraph(cnt, font);
					boolean e = StringUtils.isEmpty(cnt);
					eps[c] = (byte) (e ? 0 : 1);

				}

				String full = new String(fulleps);
				String epstr = new String(eps);
				if (epstr.equals(full))
					continue;

				boolean backed = false;
				for (int m = 0; m < pdfparag.length && m < columns; m++) {
					Paragraph p = pdfparag[m];
					PdfPCell cell = new PdfPCell(p);
					if ("*".equals(p.getContent())) {
						backed = true;
					}
					if (backed) {
						cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
					}
					table.addCell(cell);

				}

			}
			justifyTableHeader(xlsType, table, sheet.getSheetName());
			pdfdoc.add(table);
		}

	}
}

class Watermark extends PdfPageEventHelper {

	Font FONT = new Font(FontFamily.COURIER, 32, Font.BOLD,
			new GrayColor(0.95f));

	@Override
	public void onEndPage(PdfWriter writer, Document document) {
		ColumnText.showTextAligned(writer.getDirectContentUnder(),
				Element.ALIGN_CENTER, new Phrase("qujiakang@copyright", FONT),
				297.5f, 421, writer.getPageNumber() % 2 == 1 ? 45 : -45);
	}

	@Override
	public void onStartPage(PdfWriter writer, Document document) {

	}
}
